package com.dz.service.impl;

import com.dz.constant.MessageConstant;
import com.dz.constant.StatusConstant;
import com.dz.dto.OrdersSubmitDTO;
import com.dz.dto.SubmitDTO;
import com.dz.entity.*;
import com.dz.enumeration.AppHttpCodeEnum;
import com.dz.exception.SystemException;
import com.dz.mapper.OrderDetailMapper;
import com.dz.mapper.OrderMapper;
import com.dz.redis.RedisCache;
import com.dz.service.OrderService;
import com.dz.service.ShoppingCartService;
import com.dz.service.UserAddressService;
import com.dz.service.UserService;
import com.dz.utils.BeanCopyUtils;
import com.dz.vo.OrderSubmitVO;
import io.jsonwebtoken.lang.Assert;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.List;
import java.util.concurrent.TimeUnit;

/**
 * @author: DengHaoQi
 * @date: 2024/4/21 17:20
 * @description:
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class OrderServiceImpl implements OrderService {

    private final UserAddressService addressService;
    private final UserService userService;
    private final ShoppingCartService shoppingCartService;
    private final OrderMapper orderMapper;
    private final OrderDetailMapper orderDetailMapper;
    private final RedisCache redisCache;


    /*
     * 提交订单
     * */
    @Override
    @Transactional
    public OrderSubmitVO submit(SubmitDTO submitDTO) {

        OrdersSubmitDTO ordersSubmitDTO = submitDTO.getOrdersSubmitDTO();
        Long userId = submitDTO.getUserId();

        // 获取地址信息
        AddressBook address = addressService.getAddressById(ordersSubmitDTO.getAddressBookId());
        String addressStr = address.getProvinceName() + address.getDistrictName() + address.getCityName() + address.getDetail();
        // 获取支付方式
        int payMethod = ordersSubmitDTO.getPayMethod();
        // 获取手机号
        String phone = address.getPhone();
        // 获取用户信息
        User user = userService.getUserById(userId);
        Assert.notNull(user, MessageConstant.USER_INFO_ERROR);
        // 封装Order实体
        Orders orders = Orders.builder()
                .number(submitDTO.getOrderNum())
                .status(1) // 订单状态默认待付款
                .userId(userId)
                .addressBookId(ordersSubmitDTO.getAddressBookId())
                .orderTime(LocalDateTime.now())
                .payMethod(payMethod)
                .payStatus(0) // 默认未支付
                .amount(ordersSubmitDTO.getAmount())
                .remark(ordersSubmitDTO.getRemark())
                .phone(phone)
                .address(addressStr)
                .userName(user.getName())
                .consignee(address.getConsignee())
                .estimatedDeliveryTime(ordersSubmitDTO.getEstimatedDeliveryTime())
                .deliveryStatus(ordersSubmitDTO.getDeliveryStatus())
                .packAmount(ordersSubmitDTO.getPackAmount())
                .tablewareNumber(ordersSubmitDTO.getTablewareNumber())
                .tablewareStatus(ordersSubmitDTO.getTablewareStatus())
                .build();

        // 订单写入DB
        int row = orderMapper.insert(orders);
        if (row == StatusConstant.INSERT_ERROR) {
            throw new SystemException(AppHttpCodeEnum.INSERT_ERROR);
        }
        List<ShoppingCart> list = shoppingCartService.getList(userId);
        // 封装订单详情实体信息
        List<OrderDetail> orderDetailList = list.stream()
                .map(goods -> {
                    OrderDetail orderDetail = BeanCopyUtils.copyBean(goods, OrderDetail.class);
                    orderDetail.setOrderId(orders.getId());
                    return orderDetail;
                })
                .toList();
        // 写入订单详情表
        int rows = orderDetailMapper.insertBatch(orderDetailList);
        if (rows < orderDetailList.size()) {
            throw new SystemException(AppHttpCodeEnum.INSERT_ERROR);
        }

        // 订单信息存入Redis(用户id+订单id作为key)
        String redisKey = submitDTO.getOrderNum();
        redisCache.setCacheObject(redisKey,orders,5, TimeUnit.SECONDS);
        return OrderSubmitVO.builder()
                .id(orders.getId())
                .orderNumber(orders.getNumber())
                .orderAmount(orders.getAmount())
                .orderTime(orders.getOrderTime())
                .build();
    }
}
